package code18_design.factory;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

// (单例)对象工厂
public class ObjectFactory {
	// 存储对象对应的Class
	private static Map<String, Class<?>> classMap = new HashMap<String, Class<?>>();
	// 存储工厂创建的对象
	private static Map<String, Object> objs = new HashMap<String, Object>();
	
	static {
		// 加载配置文件 , 配置文件必须叫 objs.properties, 必须在 src 根目录下
		try (
				BufferedReader br = new BufferedReader(
						new InputStreamReader(
								ObjectFactory.class.getClassLoader()
								.getResourceAsStream("objs.properties")
						));
				) {
			String line = null;
			while( ( line = br.readLine() ) != null ){
				String[] arr = line.split("=");
				if (arr.length == 2) {
					// 保留 key=value 格式的 内容
					String key = arr[0];
					String value = arr[1];
					// 加载对应的Class
					Class<?> clazz = Class.forName(value);
					classMap.put(key, clazz);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			// 静态代码块中不能抛出检查异常
			// 静态代码块专用异常
			throw new ExceptionInInitializerError("工厂初始化失败");
		}
		// 先加载Class, 再创建对象
		
		// 根据 Class 创建对应的对象
		Set<String> keySet = classMap.keySet();
		for (String key : keySet) {
			Class<?> clazz = classMap.get(key);
			if (null != objs.get(key)) {
				// 说明已提前创建了其对象, 则不需要重复创建
				continue;
			}
			try {
				// 创建对象
				Object obj = clazz.newInstance();
				objs.put(key, obj);
			} catch (Exception e) {
				e.printStackTrace();
				throw new ExceptionInInitializerError("工厂中对象创建失败");
			}
		}
	}
	
	/**
	 * 根据 key 获取 对应的对象
	 * @param key
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getObj(String key) {
		T t = (T) objs.get(key);
		if (null == t) {
			// 没有对应的对象, 需要创建, 获取对应的 Class
			Class<?> c = classMap.get(key);
			if (null != c) {
				try {
					t = (T) c.newInstance();
					// 保存到 objs
					objs.put(key, t);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return t;
	}
	
}
